package sys

import (
	"io"
	"os"
	"time"
	"path"
	"meman/controllers"
	"meman/sys/basic"
	"github.com/chaosue/tplengine"
	"encoding/json"
	"meman/libs/utils"
	"encoding/base64"
	"github.com/labstack/echo"
	"github.com/labstack/echo/engine/standard"
	"github.com/chaosue/echo-sessions"
	"regexp"
	"html/template"
	"fmt"
)

type Template struct {
	templates *template.Template
}
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
	return t.templates.ExecuteTemplate(w, name, data)
}

/**
注册路由
@param

 */
func RegisterRouter() {

	e := echo.New()

	//添加静态资源
	e.Static("/static", "views/static")

	logger := basic.Logger{}

	env := basic.Config.ReceptionEnv
	viewDir := "views/**/*.tmpl"

	switch env {
	case "debug":
		logger.WriteMsg("warn", fmt.Sprintf("Running in [%v] mode...", env))
		tplEngine := tplengine.NewDebugRenderer("myname")
		tplEngine.Funcs(getFunc())
		err := tplEngine.ParseGlob(viewDir)
		if err == nil {
			e.SetRenderer(tplEngine)
		}
	case "prod":
		tplEngine := tplengine.NewRenderer("myname")
		tplEngine.Funcs(getFunc())
		err := tplEngine.ParseGlob(viewDir)
		if err == nil {
			e.SetRenderer(tplEngine)
		}
	default:
		logger.WriteMsg("error",fmt.Sprintf("Invalid env[%v], available env are: %v, %v", env, "debug", "prod"))
		os.Exit(1)
	}
	
	////添加session
	store := sessions.NewCookieStore([]byte("secret"))
	e.Use(sessions.Sessions("mysession", store))
	//设置全局session,既cookie 的存在时间和路径
	store.Options(sessions.Options{
		MaxAge: 3600,
		Path: "/",
		//Secure: true,
		//HttpOnly: true,
	})

	//添加Auth中间件,每次请求都判断是否登录
	e.Use(controllers.AuthMiddleware)


	//注册请求地址和处理方法
	e.GET("/Auth/Login", controllers.Login)
	e.GET("/Auth/LoginOut", controllers.LoginOut)
	e.GET("/", controllers.Index)
	////消息分类相关
	e.GET("/Event/MsgList/show", controllers.MsgListShow)
	e.GET("/Event/MsgList/add", controllers.MsgListAdd)
	e.POST("/Event/MsgList/add", controllers.MsgListAddPost)
	e.GET("/Event/MsgList/update", controllers.MsgListUpdate)
	e.POST("/Event/MsgList/update", controllers.MsgListUpdatePost)
	e.GET("/Event/MsgList/delete", controllers.MsgListDelete)
	//账号管理相关
	e.GET("/Event/Subscriber/show", controllers.SubscriberListShow)
	e.GET("/Event/Subscriber/add", controllers.SubscriberAdd)
	e.POST("/Event/Subscriber/add", controllers.SubscriberAddPost)
	e.GET("/Event/Subscriber/update", controllers.SubscriberUpdate)
	e.POST("/Event/Subscriber/update", controllers.SubscriberUpdatePost)
	e.GET("/Event/Subscriber/delete", controllers.SubscriberDelete)
	//订阅消息相关
	e.GET("/Event/Subscription/show", controllers.SubscriptionListShow)
	e.GET("/Event/Subscription/add", controllers.SubscriptionAdd)
	e.POST("/Event/Subscription/add", controllers.SubscriptionAddPost)
	e.GET("/Event/Subscription/update", controllers.SubscriptionUpdate)
	e.POST("/Event/Subscription/update", controllers.SubscriptionUpdatePost)
	e.GET("/Event/Subscription/delete", controllers.SubscriptionDelete)

	e.GET("/Nsq/Stats", controllers.NsqShow)
	e.GET("/Event/LogList", controllers.LogList)
	e.GET("/Event/LogDetail", controllers.LogDetail)
	//e.POST("/Event/RestoreMessage", controllers.RestoreMessage)
	//e.GET("/Event/LogDownload", controllers.LogDownload)
	e.GET("/RedisInfo/Stats", controllers.RedisInfo)
	e.GET("/RedisInfo/MessageList", controllers.MessageList)
	e.GET("/RedisInfo/MessageList/del", controllers.MessageListDel)


	// Start server
	e.Run(standard.New(basic.Config.ServerAddr))
}


func getFunc() template.FuncMap {

	return  template.FuncMap{
		"json": func(d interface{}) template.HTML {
			b, err := json.Marshal(d)
			if err != nil {
				return ""
			}
			return template.HTML(string(b))
		},
		"list": func(vals ...interface{}) []interface{} {
			return append([]interface{}{}, vals...)
		},
		"map": func() map[string]interface{} {
			return map[string]interface{}{}
		},
		"addToMap": func(name string, val interface{}, m map[string]interface{}) map[string]interface{} {
			m[name] = val
			return m
		},
		"timeFormat": func(timestamp int64) string {
			tm := time.Unix(timestamp, 0)
			return tm.Format("2006-01-02 15:04:05")
		},
		"inArray": func(val string, array []string) bool {
			flag,_ := utils.InArrayString(val, array)
			return flag
		},
		"base64Encode": func(val string) string {
			encode := base64.StdEncoding.EncodeToString([]byte(val))
			return encode
		},
		"basename": func(val string) string {
			basename := path.Base(val)
			return basename
		},
		"regular":func(rule, value string) bool {
			reg := regexp.MustCompile(rule)
			return reg.MatchString(value)
		},
		"timeFormatNano": func(timestamp float64) string {
			//纳秒没什么用 前段不显示 直接将小数舍弃转化为int64
			tm := time.Unix(int64(timestamp), 0)
			return tm.Format("2006-01-02 15:04:05")
		},
		/**
		TODO SubscriptionModify 这里defaultVal, defaultMaxVal 类型传入不正确. 数据库中全为string, 但是实际使用需要转换格式
		TODO 后面subParams 改为struct在进行修改
		TODO 这部分是进度条拉动参数默认值得一个方法
		//"timeout":func(defaultVal,  realVal, defaultMaxVal int) int {
		//	var timeout int
		//	if defaultVal > 0 {
		//		timeout = defaultVal
		//	}else if realVal != 0  {
		//		timeout = realVal * 1000
		//	}else {
		//		timeout = defaultMaxVal
		//	}
		//	return timeout
		//},

		 */
	}


}

